﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;

namespace AbpCodeBulider.DxUI
{
    public partial class WaitForm : DevExpress.XtraWaitForm.WaitForm
    {


        private static WaitForm waitForm;

        /// <summary>
        /// 标识等待窗口是否关闭
        /// </summary>
        private static bool isClose = false;


        private static bool isCreateThread = false;

        private static ManualResetEvent waitLock = new ManualResetEvent(false);
        private static ManualResetEvent loadLock = new ManualResetEvent(false);

        private static Stack<WaitFormAction> StackAction = new Stack<WaitFormAction>();

        private class WaitFormAction
        {
            public enum EnumAction
            {
                Show = 0,
                Close = 1,
                Wait = 2
            }

            public WaitFormAction(EnumAction action)
            {
                this.Action = action;
            }

            public EnumAction Action { get; set; }
            public string Description { get; set; }
            public string Caption { get; set; }
            public int SleepForShow { get; set; }

        }

        public WaitForm(string description,string caption)
        {
            InitializeComponent();
            SetDescription(description);
            SetCaption(caption);
        }

        #region 显示Loading窗口
        /// <summary>
        /// 显示Loading窗口
        /// </summary>
        /// <param name="description"></param>
        /// <param name="caption"></param>
        /// <param name="sleepForShow"></param>
        public static void ShowWaitForm(string description = "加载中", string caption = "请稍等", int sleepForShow = 100)
        {
            isClose = false;
            StackAction.Clear();
            StackAction.Push(new WaitFormAction(WaitFormAction.EnumAction.Show)
                                 {
                                     Description = description,
                                     Caption = caption,
                                     SleepForShow = sleepForShow
                                 });//添加到栈中

            if (!isCreateThread) //如果线程没有创建
            {
                waitLock.Reset();
                isCreateThread = true;
                Thread thread = new Thread(Running) { IsBackground = true };
                thread.Start();
            }
            else
            {
                waitLock.Set();
            }

        } 
        #endregion

        #region 关闭Loading窗口
        /// <summary>
        /// 关闭Loading窗口
        /// </summary>
        public static void CloseWaitForm()
        {
            isClose = true;
            StackAction.Clear();
            StackAction.Push(new WaitFormAction(WaitFormAction.EnumAction.Close));
            waitLock.Set();
        } 
        #endregion

        #region 线程处理Loading窗口
        /// <summary>
        /// 线程处理Loading窗口
        /// </summary>
        private static void Running()
        {
            while (true)
            {
                if (StackAction.Count > 0)
                {
                    WaitFormAction waitFormAction;
                    lock (StackAction)
                    {
                        waitFormAction = StackAction.Pop();
                    }

                    #region Show
                    if (waitFormAction.Action == WaitFormAction.EnumAction.Show)
                    {
                        if (waitForm != null)
                        {
                            if (isClose)
                                continue;
                            try
                            {
                                ReSetContent(waitFormAction.Description, waitFormAction.Caption,
                                             waitFormAction.SleepForShow);
                            }
                            catch
                            {

                            }
                        }
                        else
                        {
                            if (waitFormAction.SleepForShow != 0)
                            {
                                Thread.Sleep(waitFormAction.SleepForShow);
                            }
                            if (isClose)
                                continue;
                            loadLock.Reset();
                            Thread thread = new Thread(() =>
                                            {
                                                waitForm = new WaitForm(waitFormAction.Description,
                                                                        waitFormAction.Caption);
                                                Application.Run(waitForm);
                                            }) { IsBackground = true };

                            thread.Start();
                            loadLock.WaitOne();
                        }
                    }
                    #endregion

                    #region Close
                    else if (waitFormAction.Action == WaitFormAction.EnumAction.Close)
                    {
                        try
                        {
                            if (waitForm != null)
                            {
                                waitForm.Invoke((MethodInvoker)(() => waitForm.Hide()));
                                isClose = true;
                            }
                        }
                        catch (Exception)
                        {
                        }
                    }
                    #endregion

                }
                else
                {
                    waitLock.Reset();
                    waitLock.WaitOne();
                }
            }
        } 
        #endregion

        #region 设置Loading窗口的descrition和caption
        /// <summary>
        /// 设置Loading窗口的descrition和caption
        /// </summary>
        /// <param name="descrition">Loading窗口的descrition</param>
        /// <param name="caption">Loading窗口的caption</param>
        /// <param name="sleepForShow">Loading窗口延迟多少秒出现</param>
        private static void ReSetContent(string descrition, string caption, int sleepForShow)
        {
            if (waitForm != null)
            {
                try
                {
                    waitForm.SetContentInvoke(descrition, caption, sleepForShow);
                }
                catch (Exception)
                {

                }
            }
        }

        private void SetContentInvoke(string description, string caption, int sleepForShow)
        {
            this.Invoke(new ReSetContentDelete(SetCaption), caption);
            this.Invoke(new ReSetContentDelete(SetDescription), description);
            Thread.Sleep(sleepForShow);
            if (isClose)
                return;
            this.Invoke((MethodInvoker)(() =>
            {
                this.Show();
                this.Activate();
            }));
        }
        #endregion
        
        private delegate void ReSetContentDelete(string content);

        public override sealed void SetCaption(string caption)
        {
            this.progressPanel1.Caption = caption;
        }

        public override sealed void SetDescription(string description)
        {
            this.progressPanel1.Description = description;
        }

        private void WaitForm_Shown(object sender, EventArgs e)
        {
            this.Activate();
            loadLock.Set();
        }
    }
}
